package com.sxr.servlet.util;

import com.sxr.integration.SecureFileRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * Servlet请求解析工具
 * 将HttpServletRequest转换为业务请求对象
 *
 * @author SXR
 * @since 1.0.0
 */
public class ServletRequestParser {

    /** 系统保留参数列表 - 这些参数不会被包含在extraParams中 */
    private static final Set<String> RESERVED_PARAMS = new HashSet<>();
    private final String preview;
    private final String download;
    /** 预编译的正则表达式模式 - 提高性能 */
    private static final Pattern STRING_VALUE_PATTERN = Pattern.compile("\"([^\"]+)\"\\s*:\\s*\"([^\"]+)\"");
    private static final Pattern NON_STRING_VALUE_PATTERN = Pattern.compile("\"([^\"]+)\"\\s*:\\s*([^,}\\s]+)");
    private static final Pattern OBJECT_PATTERN = Pattern.compile("\"([^\"]+)\"\\s*:\\s*\\{([^}]+)\\}");

    public ServletRequestParser(String preview, String download) {
        this.preview = preview;
        this.download = download;
    }

    public ServletRequestParser() {
        this.preview = "/preview/";
        this.download = "/download/";
    }
    static {
        RESERVED_PARAMS.add("signature");
        RESERVED_PARAMS.add("expire");
        RESERVED_PARAMS.add("limit");
        RESERVED_PARAMS.add("access");
        RESERVED_PARAMS.add("token");
        RESERVED_PARAMS.add("debug");
        RESERVED_PARAMS.add("trace");
        RESERVED_PARAMS.add("preview"); // preview参数不参与签名计算，避免包含在extraParams中
    }

    /**
     * 解析安全文件请求
     *
     * @param request HTTP请求
     * @param isPreview 是否为预览模式
     * @return 安全文件请求对象
     */
    public SecureFileRequest parseSecureFileRequest(HttpServletRequest request, boolean isPreview) {
        SecureFileRequest fileRequest = new SecureFileRequest();

        // 解析路径信息
        String pathInfo = extractPathInfo(request, isPreview);
        parseTenantAndFilePath(pathInfo, fileRequest);

        // 设置基本参数
        fileRequest.setPreview(isPreview);

        // 设置签名（Servlet容器已自动进行URL解码）
        String signature = request.getParameter("signature");
        if (signature != null) {
            fileRequest.setSignature(signature);
        }

        fileRequest.setClientIp(getClientIp(request));
        fileRequest.setUserAgent(request.getHeader("User-Agent"));
        fileRequest.setRangeHeader(request.getHeader("Range"));

        // 设置过期时间
        String expireParam = request.getParameter("expire");
        if (expireParam != null && !expireParam.trim().isEmpty()) {
            try {
                fileRequest.setExpireTime(Long.parseLong(expireParam));
            } catch (NumberFormatException e) {
                // 忽略无效的过期时间参数
            }
        }

        // 设置访问限制
        String limitParam = request.getParameter("limit");
        if (limitParam != null && !limitParam.trim().isEmpty()) {
            try {
                fileRequest.setAccessLimit(Integer.parseInt(limitParam));
            } catch (NumberFormatException e) {
                // 忽略无效的限制参数
            }
        }

        // 设置请求头
        fileRequest.setHeaders(extractHeaders(request));

        // 提取extraParams（排除系统保留参数）
        fileRequest.setExtraParams(extractExtraParams(request));

        return fileRequest;
    }

    /**
     * 解析JSON请求
     *
     * @param request HTTP请求
     * @return 安全文件请求对象
     * @throws IOException IO异常
     */
    public SecureFileRequest parseJsonRequest(HttpServletRequest request) throws IOException {
        // 读取请求体
        StringBuilder jsonBuilder = new StringBuilder();
        try (BufferedReader reader = request.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                jsonBuilder.append(line);
            }
        }

        String jsonBody = jsonBuilder.toString();

        // 简单的JSON解析（生产环境建议使用专业的JSON库）
        return parseJsonToSecureFileRequest(jsonBody);
    }

    /**
     * 提取路径信息
     */
    private String extractPathInfo(HttpServletRequest request, boolean isPreview) {
        String requestURI = request.getRequestURI();
        String contextPath = request.getContextPath();

        // 移除上下文路径
        if (contextPath != null && !contextPath.isEmpty()) {
            requestURI = requestURI.substring(contextPath.length());
        }

        // 移除servlet路径前缀（现在不再有/sxr前缀）
        String prefix = isPreview ? preview : download;
        if (requestURI.startsWith(prefix)) {
            return requestURI.substring(prefix.length());
        }

        return requestURI;
    }

    /**
     * 解析租户ID和文件路径
     */
    private void parseTenantAndFilePath(String pathInfo, SecureFileRequest fileRequest) {
        if (pathInfo == null || pathInfo.trim().isEmpty()) {
            return;
        }

        // 移除开头的斜杠
        if (pathInfo.startsWith("/")) {
            pathInfo = pathInfo.substring(1);
        }

        // 简单的路径解析：/tenantId/filePath
        String[] parts = pathInfo.split("/", 2);
        if (parts.length >= 2) {
            fileRequest.setTenantId(parts[0]);
            fileRequest.setFilePath(parts[1]);
        } else if (parts.length == 1) {
            fileRequest.setFilePath(parts[0]);
        }

        // 设置文件名
        String filePath = fileRequest.getFilePath();
        if (filePath != null && !filePath.trim().isEmpty()) {
            int lastSlashIndex = filePath.lastIndexOf('/');
            if (lastSlashIndex >= 0 && lastSlashIndex < filePath.length() - 1) {
                fileRequest.setFileName(filePath.substring(lastSlashIndex + 1));
            } else {
                fileRequest.setFileName(filePath);
            }
        }
    }

    /**
     * 获取客户端IP
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 提取请求头
     */
    private Map<String, String> extractHeaders(HttpServletRequest request) {
        Map<String, String> headers = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();

        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            headers.put(headerName, headerValue);
        }

        return headers;
    }

    /**
     * 提取extraParams（排除系统保留参数）
     * 按照字典序排序确保一致性
     */
    private Map<String, String> extractExtraParams(HttpServletRequest request) {
        Map<String, String> extraParams = new HashMap<>();

        // 获取所有查询参数
        Enumeration<String> paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
            String paramName = paramNames.nextElement();

            // 跳过系统保留参数
            if (!RESERVED_PARAMS.contains(paramName.toLowerCase())) {
                String paramValue = request.getParameter(paramName);
                if (paramValue != null) {
                    // 对参数值进行URL解码
                    extraParams.put(paramName, urlDecode(paramValue));
                }
            }
        }

        return extraParams;
    }

    /**
     * 简单的JSON解析（生产环境建议使用Jackson或Gson）
     * 支持extraParams嵌套对象解析
     */
    private SecureFileRequest parseJsonToSecureFileRequest(String json) {
        SecureFileRequest request = new SecureFileRequest();

        if (json == null || json.trim().isEmpty()) {
            return request;
        }

        json = json.trim();

        // 解析基本字段
        request.setTenantId(extractJsonValue(json, "tenantId"));
        request.setFilePath(extractJsonValue(json, "filePath"));
        request.setFileName(extractJsonValue(json, "fileName"));

        // 解析布尔值
        String previewStr = extractJsonValue(json, "preview");
        if (previewStr != null) {
            request.setPreview(Boolean.parseBoolean(previewStr));
        }

        // 解析数值
        String expireTimeStr = extractJsonValue(json, "expireTime");
        if (expireTimeStr != null) {
            try {
                request.setExpireTime(Long.parseLong(expireTimeStr));
            } catch (NumberFormatException e) {
                // 忽略无效值
            }
        }

        String accessLimitStr = extractJsonValue(json, "accessLimit");
        if (accessLimitStr != null) {
            try {
                request.setAccessLimit(Integer.parseInt(accessLimitStr));
            } catch (NumberFormatException e) {
                // 忽略无效值
            }
        }

        // 解析extraParams对象
        Map<String, String> extraParams = extractJsonObject(json, "extraParams");
        if (extraParams != null && !extraParams.isEmpty()) {
            request.setExtraParams(extraParams);
        }

        return request;
    }

    /**
     * 从JSON字符串中提取指定字段的值
     * 使用预编译的正则表达式提高性能
     */
    private String extractJsonValue(String json, String fieldName) {
        // 尝试匹配字符串值
        String pattern = "\"" + fieldName + "\"\\s*:\\s*\"([^\"]+)\"";
        Pattern p = Pattern.compile(pattern);
        java.util.regex.Matcher m = p.matcher(json);
        if (m.find()) {
            return m.group(1);
        }

        // 尝试匹配非字符串值（数字、布尔值）
        pattern = "\"" + fieldName + "\"\\s*:\\s*([^,}\\s]+)";
        p = Pattern.compile(pattern);
        m = p.matcher(json);
        if (m.find()) {
            return m.group(1).trim();
        }

        return null;
    }

    /**
     * 从JSON字符串中提取指定对象字段
     */
    private Map<String, String> extractJsonObject(String json, String fieldName) {
        Map<String, String> result = new HashMap<>();

        // 查找extraParams对象的开始和结束位置
        String pattern = "\"" + fieldName + "\"\\s*:\\s*\\{([^}]+)\\}";
        java.util.regex.Pattern p = java.util.regex.Pattern.compile(pattern);
        java.util.regex.Matcher m = p.matcher(json);

        if (m.find()) {
            String objectContent = m.group(1);

            // 解析对象内容
            String[] pairs = objectContent.split(",");
            for (String pair : pairs) {
                String[] keyValue = pair.split(":", 2);
                if (keyValue.length == 2) {
                    String key = keyValue[0].trim().replaceAll("\"", "");
                    String value = keyValue[1].trim().replaceAll("\"", "");
                    result.put(key, value);
                }
            }
        }

        return result;
    }

    /**
     * URL解码 - 使用JDK自带的URLDecoder
     */
    private String urlDecode(String value) {
        if (value == null) {
            return null;
        }
        try {
            return java.net.URLDecoder.decode(value, "UTF-8");
        } catch (java.io.UnsupportedEncodingException e) {
            // UTF-8是标准编码，不会出现此异常
            throw new RuntimeException("UTF-8 encoding not supported", e);
        }
    }
}
